package net.citrite.android;

import com.android.ide.common.rendering.HardwareConfigHelper;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.api.*;
import com.android.ide.common.resources.FrameworkResources;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.common.resources.ResourceResolver;
import com.android.ide.common.resources.configuration.DeviceConfigHelper;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.common.resources.configuration.LanguageQualifier;
import com.android.ide.common.resources.configuration.RegionQualifier;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.devices.Device;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;


public class RenderTask {
    private final static Logger logger = Logger.getLogger(RenderTask.class.getName());
    private ResourceRepository projectResources;
    private IAndroidTarget androidTarget;
    private Device device;
    private LayoutLibrary layoutLibrary;
    private FrameworkResources frameworkResources;
    private ProjectCallback projectCallback = new ProjectCallback();
//    public RenderTask(ResourceRepository resourceRepository, IAndroidTarget target, Device device) {
//        this.projectResources = resourceRepository;
//        this.androidTarget = target;
//        this.device = device;
//
//        // fetch frame resource
//        createFrameResources();
//        createLayoutLibrary();
//    }

    public void run() throws IOException, XmlPullParserException {
        Map<String, FolderConfiguration> folderConfigMap = createLocalizedConfigure();
        Iterator<Map.Entry<String, FolderConfiguration>> iterator = folderConfigMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, FolderConfiguration> item = iterator.next();
            String name = item.getKey();
            FolderConfiguration config = item.getValue();
            //updateConfigure(config);
            RenderResources renderResources = createResourceResolver(config);
            for (ResourceItem resourceItem : projectResources.getResourceItemsOfType(ResourceType.LAYOUT)) {
                ResourceValue resourceValue = renderResources.getProjectResource(ResourceType.LAYOUT, resourceItem.getName());
                File layoutFile = new File(resourceValue.getValue());
                XmlParser xmlParser = XmlParser.create(projectCallback, layoutFile);
                HardwareConfigHelper hardwareConfigHelper = new HardwareConfigHelper(device);
                HardwareConfig hardwareConfig = hardwareConfigHelper.getConfig();
                int version = config.getVersionQualifier().getVersion();
                LayoutLogWrapper layoutLogWrapper = new LayoutLogWrapper(logger);
                SessionParams sessionParams = new SessionParams(xmlParser, SessionParams.RenderingMode.NORMAL, this, hardwareConfig, renderResources, projectCallback, version, version, layoutLogWrapper);
//                sessionParams.setLayoutOnly();
                sessionParams.setExtendedViewInfoMode(true);
                RenderSession session = layoutLibrary.createSession(sessionParams);
                Result result = session.getResult();
                if (result.isSuccess() == false) {
                    System.err.println(result.getErrorMessage());
                }
                displayViewObjects(session.getRootViews());
            }
        }
    }

    private Map<String, FolderConfiguration> createLocalizedConfigure() {
        FolderConfiguration defaultConfiguration = DeviceConfigHelper.getFolderConfig(device.getDefaultState());
        Map<String, FolderConfiguration> folderConfigMap = new HashMap<String, FolderConfiguration>();
        for (String lan : projectResources.getLanguages()) {
            if ("en".equals(lan)) {
                continue;
            }
            String name = lan;
            FolderConfiguration folderConfig = new FolderConfiguration();
            folderConfig.set(defaultConfiguration);
            folderConfig.setLanguageQualifier(LanguageQualifier.getQualifier(lan));
            for (String reg : projectResources.getRegions(lan)) {
                name += "-" + reg;
                folderConfig.setRegionQualifier(RegionQualifier.getQualifier("r" + reg));
            }
            folderConfigMap.put(name, folderConfig);
        }
        return folderConfigMap;
    }

    private void updateConfigure(FolderConfiguration config) {

    }
    public ResourceResolver createResourceResolver(FolderConfiguration config) {

        Map<ResourceType, Map<String, ResourceValue>> configedProjectRes =
                projectResources.getConfiguredResources(config);

        Map<ResourceType, Map<String, ResourceValue>> configedFrameworkRes =
                frameworkResources.getConfiguredResources(config);

        return ResourceResolver.create(configedProjectRes, configedFrameworkRes,
                "@style/AppTheme", true);
    }
//    private void createFrameResources() {
//        String frameResFolder = androidTarget.getPath(IAndroidTarget.RESOURCES);
//        LogWrapper logWrapper = new LogWrapper(logger);
//        FolderWrapper resFolder = new FolderWrapper(frameResFolder);
//        frameworkResources = new FrameworkResources(resFolder);
//        frameworkResources.loadResources();
//        frameworkResources.loadPublicResources(logWrapper);
//    }

//    private void createLayoutLibrary() {
//        LogWrapper logWrapper = new LogWrapper(logger);
//        File layoutLib = androidTarget.getFile(IAndroidTarget.LAYOUT_LIB);
//        layoutLibrary = LayoutLibrary.load(layoutLib.getPath(), logWrapper, "Render");
//        HashMap<String, Map<String, Integer>> enumMap = new HashMap<>();
//
//        FolderConfiguration config = new FolderConfiguration();
//        Map<ResourceType, Map<String, ResourceValue>> res = frameworkResources.getConfiguredResources(config);
//
//        // get the ATTR values
//        Map<String, ResourceValue> attrItems = res.get(ResourceType.ATTR);
//        for (ResourceValue value : attrItems.values()) {
//            if (value instanceof AttrResourceValue) {
//                AttrResourceValue attr = (AttrResourceValue) value;
//                Map<String, Integer> values = attr.getAttributeValues();
//                if (values != null) {
//                    enumMap.put(attr.getName(), values);
//                }
//            }
//        }
//
//        // get the declare-styleable values
//        Map<String, ResourceValue> styleableItems = res.get(ResourceType.DECLARE_STYLEABLE);
//
//        // get the attr from the styleable
//        for (ResourceValue value : styleableItems.values()) {
//            if (value instanceof DeclareStyleableResourceValue) {
//                DeclareStyleableResourceValue dsrc = (DeclareStyleableResourceValue) value;
//                Map<String, AttrResourceValue> attrs = dsrc.getAllAttributes();
//                if (attrs != null && attrs.size() > 0) {
//                    for (AttrResourceValue attr : attrs.values()) {
//                        Map<String, Integer> values = attr.getAttributeValues();
//                        if (values != null) {
//                            enumMap.put(attr.getName(), values);
//                        }
//                    }
//                }
//            }
//        }
//        File fontFolder = androidTarget.getFile(IAndroidTarget.FONTS);
//        File buildProp = new File(androidTarget.getLocation(), SdkConstants.FN_BUILD_PROP);
//        IAbstractFile buildFile = new FileWrapper(buildProp);
//        Map<String, String> builds = ProjectProperties.parsePropertyFile(buildFile, logWrapper);
//        LayoutLogWrapper layoutLogWrapper = new LayoutLogWrapper(logger);
//        layoutLibrary.init(builds, fontFolder, enumMap, layoutLogWrapper);
//    }

    private void displayViewObjects(List<ViewInfo> rootViews) {
        //System.out.println(Locale.getDefault());
        for (ViewInfo info : rootViews) {
            measure(info);
        }
    }
    private void measure(ViewInfo info) {
        System.out.println("ViewInfo name is " + info.getClassName());
        System.out.println("ViewInfo Height is " + (info.getBottom() - info.getTop()) + " Width is " + (info.getRight() - info.getLeft()));
        try {
            Class textView = null;
            if (info.getClassName().equals("android.widget.TextView")) {
                textView = layoutLibrary.getClassLoader().loadClass("android.widget.TextView");
            } else if (info.getClassName().equals("android.widget.Button")) {
                textView = layoutLibrary.getClassLoader().loadClass("android.widget.Button");
            }
            if (textView != null) {
                Method getPaintMethod = textView.getMethod("getPaint");
                Method getTextMethod = textView.getMethod("getText");
                Object paintObj = getPaintMethod.invoke(info.getViewObject());
                Class textPaint = layoutLibrary.getClassLoader().loadClass("android.text.TextPaint");
                Class rect = layoutLibrary.getClassLoader().loadClass("android.graphics.Rect");
                Object rectObj = rect.newInstance();
                Method measureTextMethod = textPaint.getMethod("measureText", String.class);
                Method getTextBoundsMethod = textPaint.getMethod("getTextBounds", String.class, int.class, int.class, rect);
                CharSequence text = (CharSequence) getTextMethod.invoke(info.getViewObject());
                float textLen = (float) measureTextMethod.invoke(paintObj, text.toString());
                getTextBoundsMethod.invoke(paintObj, text, 0, text.length(), rectObj);
                Method rectHeight = rect.getMethod("height");
                Method rectWidth = rect.getMethod("width");
                int textHeight = (int)rectHeight.invoke(rectObj);
                int textWidth = (int)rectWidth.invoke(rectObj);
                System.out.println();
                System.out.println(text);
                System.out.println("Text Height is " + textHeight + " Width is " + textWidth);

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

        // display the children
        List<ViewInfo> children = info.getChildren();
        if (children != null) {
            for (ViewInfo child : children) {
                measure(child);
            }
        }
    }
}
